﻿using System;
using UnityEditor;
using UnityEngine;

public class FindMissingPrefab
{
    [MenuItem("Assets/Mini Tools/Prefab/查找 Missing", false, 301)]
    private static void Main()
    {
        var guids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets" });
        for (var i = 0; i < guids.Length; i++)
        {
            var guid = guids[i];
            var path = AssetDatabase.GUIDToAssetPath(guid);
            ProcessPerPrefab(path, i, guids.Length);
        }

        EditorUtility.ClearProgressBar();
        Debug.Log("Complete");
    }

    private static void ProcessPerPrefab(string path, int curr, int total)
    {
        var o = AssetDatabase.LoadMainAssetAtPath(path);
        try
        {
            var go = (GameObject)PrefabUtility.InstantiatePrefab(o);
            ProcessPerGameObject(go, path, true);
            GameObject.DestroyImmediate(go);
            EditorUtility.DisplayProgressBar("Progress", $"total_cnt={total}; cur_cnt={curr}", curr / total);
        }
        catch (Exception e)
        {
            Debug.LogError($"e={e} path={path}");
            EditorUtility.ClearProgressBar();
        }
    }

    private static void ProcessPerGameObject(GameObject go, string prefabName, bool isRoot)
    {
        if (go.name.Contains("Missing Prefab"))
        {
            Debug.LogError($"{prefabName} exist missing prefab");
            return;
        }
        if (PrefabUtility.IsPrefabAssetMissing(go))
        {
            Debug.LogError($"{prefabName} exist missing prefab");
            return;
        }
        if (PrefabUtility.IsDisconnectedFromPrefabAsset(go))
        {
            Debug.LogError($"{prefabName} exist missing prefab");
            return;
        }
        if (!isRoot)
        {
            if (PrefabUtility.IsAnyPrefabInstanceRoot(go))
            {
                return;
            }
            GameObject root = PrefabUtility.GetNearestPrefabInstanceRoot(go);
            if (root == go)
            {
                return;
            }
        }

        var components = go.GetComponentsInChildren<UnityEngine.Component>(true);
        for (int i = 0; i < components.Length; i++)
        {
            var comp = components[i];
            if (comp == null)
            {
                Debug.LogError($"{prefabName} exist missing scripts");
                return;
            }
        }

        foreach (Transform child in go.transform)
        {
            ProcessPerGameObject(child.gameObject, prefabName, false);
        }
    }

}
